#ifndef S_MODBUS_RTU_H
#define S_MODBUS_RTU_H

#include <pthread.h>
#include <stdint.h>
#include "common_types.h"
#include "modbus/modbus.h"

// ###########################################################################
// 核心配置
// ###########################################################################
#define TEMPLATE_FILE "modbus_templates.ini"  // 设备模板文件路径
#define MAX_SECTION_LEN 32                    // 模板段名最大长度
#define MAX_KEY_LEN 32                        // 模板键名最大长度
#define MAX_VALUE_LEN 64                      // 模板值最大长度
#define MAX_REG_INIT_CNT 64                   // 寄存器初始值最大数量
#define EEPROM_ADDR_OFFSET 0x00               // EEPROM 地址存储偏移（适配硬件）
#define RESPONSE_TIMEOUT_MS 1000              // 通信响应超时

// ###########################################################################
// 模板相关结构体
// ###########################################################################
// 通信参数结构体（从模板加载）
typedef struct {
    char serial_dev[32];                  // 串口设备路径
    uint32_t baudrate;                    // 波特率
    modbus_parity_t parity;               // 校验位（NONE/ODD/EVEN）
    uint8_t data_bits;                    // 数据位
    uint8_t stop_bits;                    // 停止位
    uint8_t default_addr;                 // 默认从站地址（模板配置）
    uint16_t addr_reg;                    // 地址保存寄存器（模板配置）
} modbus_comm_param_t;

// 数据区配置结构体（从模板加载）
typedef struct {
    uint16_t coil_start;                  // 线圈起始地址
    uint16_t coil_cnt;                    // 线圈数量
    uint16_t discrete_input_start;        // 离散量输入起始地址
    uint16_t discrete_input_cnt;          // 离散量输入数量
    uint16_t hold_reg_start;              // 保持寄存器起始地址
    uint16_t hold_reg_cnt;                // 保持寄存器数量
    uint16_t input_reg_start;             // 输入寄存器起始地址
    uint16_t input_reg_cnt;               // 输入寄存器数量
} modbus_data_config_t;

// 寄存器初始值结构体
typedef struct {
    uint16_t addr;                        // 寄存器地址
    uint16_t value;                       // 初始值
} modbus_reg_init_t;

// 设备模板结构体
typedef struct {
    char dev_model[32];                    // 设备型号
    modbus_comm_param_t comm_param;        // 通信参数
    modbus_data_config_t data_config;      // 数据区配置
    modbus_reg_init_t hold_reg_init[MAX_REG_INIT_CNT]; // 保持寄存器初始值
    uint16_t hold_reg_init_cnt;            // 初始值数量
} modbus_device_template_t;

// 从站全局上下文
typedef struct {
    modbus_t *ctx;                        // libmodbus 上下文
    pthread_t recv_thread;                // 接收处理线程
    pthread_t data_update_thread;          // 数据更新线程
    modbus_device_template_t template;     // 加载的设备模板
    uint8_t current_addr;                 // 当前从站地址（EEPROM 加载优先）
    // 动态数据区（模板配置分配）
    uint8_t *coils;                       // 线圈（可读写）
    uint8_t *discrete_inputs;             // 离散量输入（只读）
    uint16_t *hold_regs;                  // 保持寄存器（可读写）
    uint16_t *input_regs;                 // 输入寄存器（只读）
    // 温湿度专用数据（统计用）
    int16_t temp_history[10];             // 最近10次温度采样
    int16_t humi_history[10];             // 最近10次湿度采样
    uint8_t history_idx;                  // 采样历史索引
    uint32_t sample_cnt;                  // 累计采样次数
    int16_t temp_max;                     // 24小时最高温度
    int16_t temp_min;                     // 24小时最低温度
    int16_t humi_max;                     // 24小时最高湿度
    int16_t humi_min;                     // 24小时最低湿度
    // 同步锁
    pthread_mutex_t ctx_mutex;            // 上下文访问锁
    pthread_mutex_t data_mutex;           // 数据区访问锁
    uint8_t is_running;                   // 从站运行状态
} modbus_slave_ctx_t;

// ###########################################################################
// 外部接口
// ###########################################################################
int modbus_template_parse(modbus_device_template_t *tml); // 解析模板文件
int modbus_slave_init(void);                                  // 初始化从站（含模板加载+EEPROM读取）
int modbus_slave_start(void);                                 // 启动从站
int modbus_slave_stop(void);                                  // 停止从站
int modbus_slave_deinit(void);                                // 销毁从站
uint8_t eeprom_read_addr(void);                               // 从EEPROM读取地址（适配硬件）
int eeprom_write_addr(uint8_t addr);                          // 向EEPROM写入地址（适配硬件）

#endif //S_MODBUS_RTU_H
